﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using EntityFramework.Extensions;
using Infrastructure.Extend;

namespace Domain.Repository
{
    /// <summary>
    /// DbSet扩展
    /// <remarks></remarks>
    /// </summary>  
    public static class DbSetExtended
    {
        #region 查询方法的扩展
        /// <summary>      
        /// Select方法的补充      
        /// rpy.SelectEx(item =>new TNew(){})等同rpy.Select(item => new TNew(){f1 = item.f1, f2 = item.f2 ,...})    
        /// rpy.SelectEx(item =>new TNew(){f1 = "something"})等同rpy.Select(item => new TNew(){ f1 ="something", f2 = item.f2 ,...})
        /// 其它选择方法和原始Select方法一致
        /// </summary>        
        /// <typeparam name="T">源实体类型</typeparam>
        /// <typeparam name="TNew">新的实体类型</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="selector">新对象实例</param>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static IQueryable<TNew> SelectEx<T, TNew>(this IQueryable<T> source, Expression<Func<T, TNew>> selector) where T : class
        {
            if (selector == null)
            {
                throw new ArgumentNullException();
            }

            var body = selector.Body as MemberInitExpression;
            if (body != null)
            {
                var targetType = typeof(TNew);
                var targetProperties = targetType.GetProperties().ToList();
                var sourceProperties = typeof(T).GetProperties();

                var parameter = selector.Parameters[0];
                var bindedMembers = body.Bindings.Select(b => b.Member).ToList();
                var needBindProroties = targetProperties.Where(p => bindedMembers.Exists(m => m.Name.Equals(p.Name)) == false);

                var allBindings = body.Bindings.ToList();
                foreach (var property in needBindProroties)
                {
                    var sourceProperty = sourceProperties.FirstOrDefault(item => item.Name.Equals(property.Name));
                    if (sourceProperty != null)
                    {
                        var memberExp = Expression.MakeMemberAccess(parameter, sourceProperty);
                        var binding = Expression.Bind(property, memberExp);
                        allBindings.Add(binding);
                    }
                }

                var targetNew = Expression.New(targetType);
                var bodyNew = Expression.MemberInit(targetNew, allBindings);
                selector = (Expression<Func<T, TNew>>)Expression.Lambda(bodyNew, parameter);
            }

            return source.Select(selector);
        }
        #endregion

        #region 添加方法扩展
        /// <summary>
        /// 添加实体
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="dbSet">表操作对象</param>
        /// <param name="entitys">多个实体</param>
        /// <returns></returns>
        public static void Add<T>(this DbSet<T> dbSet, IEnumerable<T> entitys) where T : EntityBase
        {
            foreach (var entity in entitys)
            {             
                dbSet.Add(entity);
            }
        }
        #endregion

        #region 删除方法扩展

        /// <summary>
        /// 移除实体
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="dbSet">表操作对象</param>
        /// <param name="id">实体ID</param>
        /// <returns></returns>
        public static void Remove<T>(this DbSet<T> dbSet, Guid id) where T : EntityBase
        {
            T entity = dbSet.Find(id);
            if (entity != null)
            {
                dbSet.Remove(entity);
            }
        }

        /// <summary>
        /// 移除实体
        /// 返回受影响行数
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="dbSet">表操作对象</param>
        /// <param name="ids">实体ID集合</param>
        /// <returns></returns>
        public static int Remove<T>(this DbSet<T> dbSet, IEnumerable<Guid> ids) where T : EntityBase
        {
            return dbSet.Remove(e => ids.Contains(e.ID));
        }

        /// <summary>
        /// 移除实体
        /// 返回受影响行数
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="dbSet">表操作对象</param>
        /// <param name="entityArray">实体集合</param>
        /// <returns></returns>
        public static int Remove<T>(this DbSet<T> dbSet, IEnumerable<T> entityArray) where T : EntityBase
        {
            var q = from e in entityArray select e.ID;
            var ids = q.ToList();
            return dbSet.Remove(e => ids.Contains(e.ID));
        }

        /// <summary>
        /// 批量删除
        /// 返回受影响行数
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="filterExpression">过滤表示式</param>
        /// <returns></returns>
        public static int Remove<T>(this IQueryable<T> source, Expression<Func<T, bool>> filterExpression) where T : class
        {
            return BatchExtensions.Delete<T>(source, filterExpression);
        }

        #endregion

        #region 更新方法扩展
        /// <summary>
        /// 更新实体
        /// 如果上下文不含有实体的跟踪,则以实体的数据更新数据库对应的内容      
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="dbSet">表操作对象</param>
        /// <param name="context">数据库上下文</param>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public static void Update<T>(this DbSet<T> dbSet, DbContext context, T entity) where T : EntityBase
        {
            var entry = context.Entry(entity);

            if (entry.State == EntityState.Detached)
            {
                T source = dbSet.Find(entity.ID);
                Type type = typeof(T);

                PropertyInfo[] propertys = typeof(T).GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    object value = pi.GetValue(entity, null);
                    var p = type.GetProperty(pi.Name);
                    if (p.GetCustomAttributes(typeof(NotMappedAttribute), false).Length == 0)
                    {
                        type.GetProperty(pi.Name).SetValue(source, value, null);
                    }
                }
            }
        }

        /// <summary>
        /// 批量更新
        /// 返回受影响行数
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="dbSet">数据源</param>
        /// <param name="updateExpression"></param>
        /// <returns></returns>
        public static int Update<T>(this DbSet<T> dbSet, Expression<Func<T, T>> updateExpression) where T : class
        {
            return BatchExtensions.Update<T>(dbSet, updateExpression);
        }


        /// <summary>
        /// 批量更新
        /// 返回受影响行数
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="dbSet">数据源</param>
        /// <param name="filterExpression">过滤表达式</param>
        /// <param name="updateExpression">更新表达式</param>
        /// <returns></returns>
        public static int Update<T>(this DbSet<T> dbSet, Expression<Func<T, bool>> filterExpression, Expression<Func<T, T>> updateExpression) where T : class
        {
            return BatchExtensions.Update<T>(dbSet, filterExpression, updateExpression);
        }
        #endregion

        #region 分页方法扩展
        /// <summary>
        /// 执行分页            
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="source">数据源</param>    
        /// <param name="pageIndex">分页索引</param>
        /// <param name="pageSize">分页大小</param>
        /// <returns></returns>
        public static PageInfo<T> ToPage<T>(this IOrderedQueryable<T> source, int pageIndex, int pageSize) where T : class
        {
            int total = source.Count();
            var data = source.Skip(pageIndex * pageSize).Take(pageSize).ToList();
            var page = new PageInfo<T>(total, data);
            return page;
        }

        /// <summary>
        /// 获取所有记录的分布方法扩展            
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="source">数据源</param>    
        /// <param name="pageIndex">分页索引</param>
        /// <param name="pageSize">分页大小</param>
        /// <returns></returns>
        public static PageInfo<T> ToPage<T>(this IOrderedQueryable<T> source) where T : class
        {
            var data = source.ToList();
            var page = new PageInfo<T>(data.Count, data);
            return page;
        }
        #endregion

        #region 关联外键数据加载扩展方法
        /// <summary>
        /// 加载外键关联数据的字段
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <typeparam name="Tkey">实体的字段</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="keySelector">所选的字段</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static IQueryable<T> Include<T, Tkey>(this IQueryable<T> source, Expression<Func<T, Tkey>> keySelector) where T : class
        {
            if (keySelector == null)
            {
                throw new ArgumentNullException();
            }

            MemberExpression body = keySelector.Body as MemberExpression;
            if (body == null || body.Member.DeclaringType.IsAssignableFrom(typeof(T)) == false || body.Expression.NodeType != ExpressionType.Parameter)
            {
                throw new ArgumentException();
            }
            else
            {
                string path = body.Member.Name;
                return source.Include(path);
            }
        }

        /// <summary>
        /// 加载所有外键关联数据的字段
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="source">数据源</param>
        /// <returns></returns>
        public static IQueryable<T> Include<T>(this IQueryable<T> source) where T : class
        {
            Func<PropertyInfo, bool> isEntityFun = (item) =>
            {
                var isEntity = typeof(EntityBase).IsAssignableFrom(item.PropertyType);
                var isEntityGeneric = item.PropertyType.IsGenericType && typeof(EntityBase).IsAssignableFrom(item.PropertyType.GetGenericArguments().FirstOrDefault());
                return isEntity || isEntityGeneric;
            };

            // 保留从EntityBase类型派生的属性
            // 保留从集合派生的属性
            var includeTypes = typeof(T).GetProperties().Where(item => isEntityFun(item)).Select(item => item.Name);

            IQueryable<T> queryable = source;
            foreach (var include in includeTypes)
            {
                queryable = queryable.Include(include);
            }
            return queryable;
        }

        /// <summary>
        /// 加载相关外键关联数据的字段
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="source">数据源</param>
        /// <returns></returns>
        public static IQueryable<T> Include<T>(this IQueryable<T> source, string[] paths) where T : class
        {
            var q = source;
            foreach (var path in paths)
            {
                q = q.Include(path);
            }
            return q;
        }

        #endregion

        #region 排序扩展
        /// <summary>
        /// 排序公共方法
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="orderByKey">排序键排序键(不分大小写)</param>
        /// <param name="orderByMethod">排序方法</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        private static IOrderedQueryable<T> OrderByCommon<T>(IQueryable<T> source, string orderByKey, string orderByMethod) where T : class
        {
            if (string.IsNullOrEmpty(orderByKey))
            {
                throw new ArgumentNullException("orderByKey");
            }

            Type sourceTtype = typeof(T);
            PropertyInfo keyProperty = sourceTtype.GetProperties().FirstOrDefault(p => p.Name.ToLower().Equals(orderByKey.Trim().ToLower()));
            if (keyProperty == null)
            {
                throw new ArgumentException("orderByKey不存在...");
            }

            var param = Expression.Parameter(sourceTtype, "item");
            var body = Expression.MakeMemberAccess(param, keyProperty);
            var orderByLambda = Expression.Lambda(body, param);

            var resultExp = Expression.Call(typeof(Queryable), orderByMethod, new Type[] { sourceTtype, keyProperty.PropertyType }, source.Expression, Expression.Quote(orderByLambda));
            var ordereQueryable = source.Provider.CreateQuery<T>(resultExp) as IOrderedQueryable<T>;
            return ordereQueryable;
        }

        /// <summary>
        /// 排序
        /// 选择升序或降序
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="orderByKey">排序键排序键(不分大小写)</param>
        /// <param name="ascending">是否升序</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string orderByKey, bool ascending) where T : class
        {
            var methodName = ascending ? "OrderBy" : "OrderByDescending";
            return DbSetExtended.OrderByCommon(source, orderByKey, methodName);
        }

        /// <summary>
        /// 排序次项
        /// 选择升序或降序
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="orderByKey">排序键(不分大小写)</param>
        /// <param name="ascending">是否升序</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string orderByKey, bool ascending) where T : class
        {
            var methodName = ascending ? "ThenBy" : "ThenByDescending";
            return DbSetExtended.OrderByCommon(source, orderByKey, methodName);
        }

        /// <summary>
        /// 多字段混合排序       
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="orderByString">排序字符串：例如CreateTime desc, ID asc 不区分大小写</param>
        /// <exception cref="ArgumentNullException">orderByString</exception>
        /// <returns></returns>
        public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string orderByString) where T : class
        {
            Func<string[], bool> descFun = (item) => item.Length > 1 && item[1].Trim().ToLower().Equals("desc");

            var parameters = orderByString
                .Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                .Select(item => item.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries))
                .Select(item => new { Key = item.FirstOrDefault(), Asc = !descFun(item) })
                .ToList();

            if (parameters.Count == 0)
            {
                throw new ArgumentNullException("orderByString");
            }

            var firstP = parameters.FirstOrDefault();
            var orderQuery = source.OrderBy(firstP.Key, firstP.Asc);
            parameters.Skip(1).ToList().ForEach(p => orderQuery = orderQuery.ThenBy(p.Key, p.Asc));

            return orderQuery;
        }

        /// <summary>
        /// 排序
        /// 选择升序或降序
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <typeparam name="TKey">排序键</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="orderKeySelector">排序器</param>
        /// <param name="ascending">是否升序</param>
        /// <returns></returns>
        public static IOrderedQueryable<T> OrderBy<T, TKey>(this IQueryable<T> source, Expression<Func<T, TKey>> orderKeySelector, bool ascending)
        {
            if (ascending)
            {
                return source.OrderBy(orderKeySelector);
            }
            else
            {
                return source.OrderByDescending(orderKeySelector);
            }
        }

        /// <summary>
        /// 次项排序
        /// 选择升序或降序
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <typeparam name="TKey">排序键</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="orderKeySelector">排序器</param>
        /// <param name="ascending">是否升序</param>
        /// <returns></returns>
        public static IOrderedQueryable<T> ThenBy<T, TKey>(this IOrderedQueryable<T> source, Expression<Func<T, TKey>> orderKeySelector, bool ascending)
        {
            if (ascending)
            {
                return source.ThenBy(orderKeySelector);
            }
            else
            {
                return source.ThenByDescending(orderKeySelector);
            }
        }
        #endregion

        #region 动态执行Sql语句扩展
        /// <summary>
        /// 执行Sql查询       
        /// <example>SqlQuery("select * from [Table] where name=@name and password=@password", "abc", "123456")</example>
        /// </summary>
        /// <param name="database">数据库</param>
        /// <param name="sql">sql语句</param>
        /// <param name="values">值或参数[可空]</param>       
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static DataTable SqlQuery(this Database database, string sql, params object[] values)
        {
            using (SqlConnection con = new SqlConnection(database.Connection.ConnectionString))
            {
                using (SqlCommand cmd = new SqlCommand(sql, con))
                {
                    con.Open();
                    var parameters = DbSetExtended.MakeSqlParameters(sql, values);
                    cmd.Parameters.AddRange(parameters);
                    using (SqlDataAdapter dataAdapter = new SqlDataAdapter(cmd))
                    {
                        using (DataSet dataSet = new DataSet())
                        {
                            dataAdapter.Fill(dataSet);
                            return dataSet.Tables[0];
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 执行Sql查询 返回执行后第一行第一列的值      
        /// <example>SqlQuery("select count(*) from [Table] where name=@name and password=@password", "abc", "123456")</example>
        /// </summary>
        /// <param name="database">数据库</param>
        /// <param name="sql">sql语句</param>
        /// <param name="values">值或参数[可空]</param>       
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static object ExecuteScalar(this Database database, string sql, params object[] values)
        {
            using (SqlConnection con = new SqlConnection(database.Connection.ConnectionString))
            {
                using (SqlCommand cmd = new SqlCommand(sql, con))
                {
                    con.Open();
                    var parameters = DbSetExtended.MakeSqlParameters(sql, values);
                    cmd.Parameters.AddRange(parameters);
                    return  cmd.ExecuteScalar();
                }
            }
        }

        /// <summary>
        /// 执行不带参数的Sql查询 返回执行后第一行第一列的值      
        /// <example>SqlQuery("select count(*) from [Table] where name=@name and password=@password", "abc", "123456")</example>
        /// </summary>
        /// <param name="database">数据库</param>
        /// <param name="sql">sql语句</param>
        /// <param name="values">值或参数[可空]</param>       
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        public static object ExecuteScalarNoPara(this Database database, string sql)
        {
            using (SqlConnection con = new SqlConnection(database.Connection.ConnectionString))
            {
                using (SqlCommand cmd = new SqlCommand(sql, con))
                {
                    con.Open();
                    return cmd.ExecuteScalar();
                }
            }
        }

        /// <summary>
        /// 表或视图分页
        /// </summary>
        /// <param name="database">数据库</param>
        /// <param name="viewName">表名</param>
        /// <param name="fieldNames">所选字段</param>
        /// <param name="whereString">滤过条件[可空]</param>
        /// <param name="orderString">排序字符串</param>
        /// <param name="pageIndex">页面索引</param>
        /// <param name="pageSize">分页大小</param>
        /// <param name="pageSize">总记录条目</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <returns></returns>
        private static DataTable SqlQueryTable(this Database database, string viewName, string fieldNames, string whereString, string orderString, int pageIndex, int pageSize, out int totalCount)
        {
            if (string.IsNullOrEmpty(viewName) || string.IsNullOrEmpty(fieldNames) || string.IsNullOrEmpty(orderString))
            {
                throw new ArgumentNullException();
            }
            var parameters = DbSetExtended.MakeSqlParameters(
                "@TableName,@Fields,@OrderField,@sqlWhere,@pageSize,@pageIndex,@TotalPage,@totalRecord",
                viewName, fieldNames, orderString, whereString, pageSize, pageIndex + 1, 0, 0);

            parameters[6].Direction = ParameterDirection.Output;
            parameters[7].Direction = ParameterDirection.Output;

            using (SqlConnection con = new SqlConnection(database.Connection.ConnectionString))
            {
                using (SqlCommand cmd = new SqlCommand("proc_common_page", con))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddRange(parameters);
                    con.Open();
                    using (SqlDataAdapter dataAdapter = new SqlDataAdapter(cmd))
                    {
                        using (DataSet dataSet = new DataSet())
                        {
                            dataAdapter.Fill(dataSet);
                            totalCount = Convert.ToInt32(parameters.Last().Value);
                            return dataSet.Tables[0];
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 模糊查询
        /// </summary>
        /// <param name="database"></param>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKeyName">查询返回字段</param>
        /// <param name="contentFieldName">比较字段</param>
        /// <param name="selectNumber">查询条数</param>
        /// <param name="splitString">匹配字符分隔标记</param>
        /// <param name="words">匹配字符组合字符串</param>
        /// <returns></returns>
        private static DataTable SqlSuperLike(this Database database, string tableName, string primaryKeyName, string contentFieldName, int selectNumber, string splitString, string words)
        {
            if (string.IsNullOrEmpty(tableName) || string.IsNullOrEmpty(primaryKeyName))
            {
                throw new ArgumentNullException();
            }

            var parameters = DbSetExtended.MakeSqlParameters(
        "@TableName,@primaryKeyName,@contentFieldName,@selectNumber ,@splitString ,@words ",
                tableName, primaryKeyName, contentFieldName, selectNumber, splitString, words);

            using (SqlConnection con = new SqlConnection(database.Connection.ConnectionString))
            {
                using (SqlCommand cmd = new SqlCommand("proc_Common_SuperLike", con))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddRange(parameters);
                    con.Open();
                    using (SqlDataAdapter dataAdapter = new SqlDataAdapter(cmd))
                    {
                        using (DataSet dataSet = new DataSet())
                        {
                            dataAdapter.Fill(dataSet);
                            //totalCount = Convert.ToInt32(parameters.Last().Value);
                            return dataSet.Tables[0];
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 未完成作业的分页 _lxy
        /// </summary>
        /// <param name="database">数据库</param>
        /// <param name="viewName">表名</param>
        /// <param name="viewName">用户名</param>
        /// <param name="viewName">系统ID</param>        /// 
        /// <param name="fieldNames">所选字段</param>
        /// <param name="whereString">滤过条件[可空]</param>
        /// <param name="orderString">排序字符串</param>
        /// <param name="pageIndex">页面索引</param>
        /// <param name="pageSize">分页大小</param>
        /// <param name="pageSize">总记录条目</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <returns></returns>
        public static DataTable SqlQueryTable(this Database database,string proc,string strUserID,string strSystemID, string fieldNames, string whereString, string orderString, int pageIndex, int pageSize, out int totalCount)
        {
            if (string.IsNullOrEmpty(strUserID) || string.IsNullOrEmpty(strSystemID) || string.IsNullOrEmpty(fieldNames) || string.IsNullOrEmpty(orderString))
            {
                throw new ArgumentNullException();
            }

            var parameters = DbSetExtended.MakeSqlParameters(
                "@UserID,@SystemID,@Fields,@OrderField,@sqlWhere,@pageSize,@pageIndex,@TotalPage,@totalRecord",
                strUserID,strSystemID, fieldNames, orderString, whereString, pageSize, pageIndex + 1, 0, 0);

            parameters[7].Direction = ParameterDirection.Output;
            parameters[8].Direction = ParameterDirection.Output;

            using (SqlConnection con = new SqlConnection(database.Connection.ConnectionString))
            {
                using (SqlCommand cmd = new SqlCommand(proc, con))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddRange(parameters);
                    con.Open();
                    using (SqlDataAdapter dataAdapter = new SqlDataAdapter(cmd))
                    {
                        using (DataSet dataSet = new DataSet())
                        {
                            dataAdapter.Fill(dataSet);
                            totalCount = Convert.ToInt32(parameters.Last().Value);
                            return dataSet.Tables[0];
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 表或视图分页
        /// </summary>
        /// <typeparam name="T">映射类型</typeparam>
        /// <param name="database">数据库</param>
        /// <param name="viewName">表名</param>
        /// <param name="fieldNames">所选字段</param>
        /// <param name="whereString">滤过条件[可空]</param>
        /// <param name="orderString">排序字符串</param>
        /// <param name="pageIndex">页面索引</param>
        /// <param name="pageSize">分页大小</param>
        /// <returns></returns>
        public static PageInfo<T> ToPage<T>(this Database database, string viewName, Expression<Func<T, object>> selector, string whereString, string orderString, int pageIndex, int pageSize) where T : class,new()
        {
            var bodyNew = selector.Body as NewExpression;
            if (bodyNew != null)
            {
                var fields = bodyNew.Arguments.Select(item => item as MemberExpression).Where(item => item != null).Select(item => item.Member.Name);
                return database.ToPage<T>(viewName, string.Join(",", fields), whereString, orderString, pageIndex, pageSize);
            }

            var bodyParameter = selector.Body as ParameterExpression;
            if (bodyParameter != null)
            {
                var fields = typeof(T).GetProperties().Where(item => item.GetCustomAttributes(typeof(NotMappedAttribute), false).Length == 0).Select(item => item.Name);
                return database.ToPage<T>(viewName, string.Join(",", fields), whereString, orderString, pageIndex, pageSize);
            }

            throw new NotSupportedException("selector");
        }

        /// <summary>
        /// 表或视图分页
        /// </summary>
        /// <typeparam name="T">映射类型</typeparam>
        /// <param name="database">数据库</param>
        /// <param name="viewName">表名</param>
        /// <param name="fieldNames">所选字段</param>
        /// <param name="whereString">滤过条件[可空]</param>
        /// <param name="orderString">排序字符串</param>
        /// <param name="pageIndex">页面索引</param>
        /// <param name="pageSize">分页大小</param>
        /// <returns></returns>
        public static PageInfo<T> ToPage<T>(this Database database, string viewName, string fieldNames, string whereString, string orderString, int pageIndex, int pageSize) where T : class,new()
        {
            int totalCount = 0;
            var table = database.SqlQueryTable(viewName, fieldNames, whereString, orderString, pageIndex, pageSize, out totalCount);
            return new PageInfo<T>(totalCount, table.ToList<T>());
        }

        /// <summary>
        /// 模糊查询
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKeyName">查询返回字段</param>
        /// <param name="contentFieldName">比较字段</param>
        /// <param name="selectNumber">查询条数</param>
        /// <param name="splitString">匹配字符分隔标记</param>
        /// <param name="words">匹配字符组合字符串</param>
        /// <returns></returns>
        public static PageInfo<T> SuperLike<T>(this Database database, string tableName, string primaryKeyName, string contentFieldName, int selectNumber, string splitString, string words) where T : class,new()
        {
            int totalCount = 0;
            var table = database.SqlSuperLike(tableName, primaryKeyName, contentFieldName, selectNumber, splitString, words);
            return new PageInfo<T>(totalCount, table.ToList<T>());
        }

        /// <summary>
        /// 表或视图分页
        /// </summary>
        /// <typeparam name="T">映射类型</typeparam>
        /// <param name="database">数据库</param>
        /// <param name="viewName">表名</param>
        /// <param name="fieldNames">所选字段</param>
        /// <param name="whereString">滤过条件[可空]</param>
        /// <param name="orderString">排序字符串</param>
        /// <param name="pageIndex">页面索引</param>
        /// <param name="pageSize">分页大小</param>
        /// <returns></returns>
        public static PageInfo<T> ToPage<T>(this Database database, string proc, string strUserID, string strSystemID, string fieldNames, string whereString, string orderString, int pageIndex, int pageSize) where T : class,new()
        {
            int totalCount = 0;
            var table = database.SqlQueryTable(proc, strUserID, strSystemID, fieldNames, whereString, orderString, pageIndex, pageSize, out totalCount);
            return new PageInfo<T>(totalCount, table.ToList<T>());
        }
        /// <summary>
        /// 表或视图分页
        /// </summary>       
        /// <param name="database">数据库</param>
        /// <param name="viewName">表名</param>
        /// <param name="fieldNames">所选字段</param>
        /// <param name="whereString">滤过条件[可空]</param>
        /// <param name="orderString">排序字符串</param>
        /// <param name="pageIndex">页面索引</param>
        /// <param name="pageSize">分页大小</param>
        /// <returns></returns>
        public static PageInfo<dynamic> ToPage(this Database database, string viewName, string fieldNames, string whereString, string orderString, int pageIndex, int pageSize)
        {
            int totalCount = 0;
            var table = database.SqlQueryTable(viewName, fieldNames, whereString, orderString, pageIndex, pageSize, out totalCount);
            return new PageInfo<dynamic>(totalCount, table.ToList());
        }

        /// <summary>
        /// 根据sql语句和参数的值动态生成Sqlparameter
        /// </summary>
        /// <param name="sql">sql语句</param>
        /// <param name="values">值或参数[可空]</param>        
        /// <exception cref="ArgumentException"></exception>
        /// <returns></returns>
        private static SqlParameter[] MakeSqlParameters(string sql, params object[] values)
        {
            Func<object[], bool> isParamererFun = (items) =>
            {
                if (values != null && values.Length > 0)
                {
                    bool notParameter = values.ToList().Exists(item => typeof(SqlParameter).Equals(item.GetType()) == false);
                    return !notParameter;
                }
                return true;
            };

            if (isParamererFun(values) == true)
            {
                if (values == null)
                {
                    return new SqlParameter[] { };
                }
                return values as SqlParameter[];
            }

            var matches = Regex.Matches(sql, @"@\w+");
            var paramNameList = new List<string>();

            foreach (Match m in matches)
            {
                if (paramNameList.Contains(m.Value) == false)
                {
                    paramNameList.Add(m.Value);
                }
            }

            if (paramNameList.Count > 0)
            {
                if (values == null || values.Length < paramNameList.Count)
                {
                    throw new ArgumentException("values的元素数目和Sql语句不匹配");
                }
            }

            int i = 0;
            var parameters = new SqlParameter[values.Length];
            foreach (var pName in paramNameList)
            {
                parameters[i] = new SqlParameter(pName, values[i]);
                i++;
            }
            return parameters;
        }

        /// <summary>
        /// 其它成员查重分页（石家仁 2015-7-3）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="database"></param>
        /// <param name="viewName"></param>
        /// <param name="selector"></param>
        /// <param name="whereString"></param>
        /// <param name="orderString"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public static PageInfo<T> GetEqualKeyMember<T>(this Database database, string viewName, Expression<Func<T, object>> selector, string whereString, string orderString, int pageIndex, int pageSize) where T : class,new()
        {
            var bodyNew = selector.Body as NewExpression;
            if (bodyNew != null)
            {
                var fields = bodyNew.Arguments.Select(item => item as MemberExpression).Where(item => item != null).Select(item => item.Member.Name);
                return database.ToPage<T>(viewName, string.Join(",", fields), whereString, orderString, pageIndex, pageSize);
            }

            var bodyParameter = selector.Body as ParameterExpression;
            if (bodyParameter != null)
            {
                var fields = typeof(T).GetProperties().Where(item => item.GetCustomAttributes(typeof(NotMappedAttribute), false).Length == 0).Select(item => item.Name);
                //return database.ToPage<T>(viewName, string.Join(",", fields), whereString, orderString, pageIndex, pageSize);
                //return database.ToPage<T>(viewName, "*", whereString, orderString, pageIndex, pageSize);
                string fieldNames = string.Join(",", fields);
                fieldNames = "A." + fieldNames.Replace(",", ",A.");
                int totalCount = 0;
                var table = database.SqlQueryTable(viewName, fieldNames, whereString, orderString, pageIndex, pageSize, out totalCount);
                return new PageInfo<T>(totalCount, table.ToList<T>());
            }

            throw new NotSupportedException("selector");
        }
        #endregion

    }
}
